import StringIO
from django import template
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.forms import ValidationError
from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render_to_response

from lxml import etree
from lxml.etree import Element, SubElement
from transsys import TranssysProgramParser
from trsysmodis import SimGenexObjectiveFunctionParser, ExpressionSet
from sgx import _get_transsys_program_by_name


def home(request):
    sessionInitilizer(request)
    return render_to_response('index.html',
                              {},
                              context_instance=template.RequestContext(request))

def help(request):
    sessionInitilizer(request)
    return render_to_response('help.html',
                              {},
                              context_instance=template.RequestContext(request))

def aboutUs(request):
    sessionInitilizer(request)
    return render_to_response('about_us.html',
                              {},
                              context_instance=template.RequestContext(request))

def exportWorkspace(request):
    sessionInitilizer(request)
    root = Element("TranssysWorkbench")
    if request.session.has_key("ts_programs"):
        ts_programs = request.session["ts_programs"]
        ts_programs_node = SubElement(root, "TranssysPrograms")
        for tp in ts_programs:
            tp_node = SubElement(ts_programs_node, "TranssysProgram")
            ts_code_node = SubElement(tp_node, "TranssysCode")
            ts_code_node.text = str(tp["tp"])
            
            """
            data_sets_node = SubElement(tp_node, "DataSets")
            if tp.has_key("data_set"):
                for k, v in tp["data_set"].items():
                    data_set_node = SubElement(data_sets_node, "DataSet")
                    data_set_node.set("name", k)
                    for k1,v1 in v.items():
                        fc_node = SubElement(data_set_node, "FactorConcentration")
                        fc_node.set("name", k1)
                        fc_node.text = str(v1)
            """
    if request.session.has_key("sgx_programs"):
        sgx_programs = request.session["sgx_programs"]
        sgx_programs_node = SubElement(root, "SimgenexPrograms")
        for sgx in sgx_programs:
            print sgx
            sgx_node = SubElement(sgx_programs_node, "SimgenexProgram")
            sgx_node.set("name", sgx["name"])
            sgx_node.set("description", sgx["desc"])
            sgx_code_node = SubElement(sgx_node, "SimgenexCode")
            sgx_code_node.text = str(sgx["sgx"])
            sgx_target_tp_node = SubElement(sgx_node, "TargetTranssysPrograms")
            for target_tp in sgx["target_tp"]:
                target_tp_node = SubElement(sgx_target_tp_node, "TargetTranssysProgram")
                target_tp_node.text = target_tp.name

            sgx_target_data_node = SubElement(sgx_node, "TargetExpressionData")
            if sgx.has_key("target_expression_data"):
                for name, target_data in sgx["target_expression_data"].items():
                    target_data_node = SubElement(sgx_target_data_node, "ExpressionSet")
                    target_data_node.set("name", name)
                    data = StringIO.StringIO("")
                    target_data.write_expression_data(data)
                    target_data_node.text = data.getvalue()
    if request.session.has_key("initial_states"):
        inital_states_node = SubElement(root, "InitialStates")
        for k, v in request.session["initial_states"].items():
                    data_set_node = SubElement(inital_states_node, "InitialState")
                    data_set_node.set("name", k)
                    for k1,v1 in v.items():
                        fc_node = SubElement(data_set_node, "FactorConcentration")
                        fc_node.set("name", k1)
                        fc_node.text = str(v1)
    xml = etree.tostring(root, pretty_print=True, xml_declaration=True)
    

    #return render_to_response('xml.html',
    #                            {'xmlcode':xml},
    #                            context_instance=template.RequestContext(request))
    #create response object
    response = HttpResponse(mimetype='text/xml')
    response['Content-Disposition'] = 'attachment; filename=TranssysWorkbench.xml'
    response.write(xml)
    return response

def importWorkspace(request):
    """Import workspace from uploading file"""
    sessionInitilizer(request)
    if(request.method == "GET"):
        return render_to_response('importWorkspace.html',
                                  context_instance=template.RequestContext(request))
    elif(request.method== "POST"):
        try:
            xml_file = request.FILES["ws_file"]
            #TODO: Validate xml file by DTD or XML Schema
            
            #Import workspace to session
            #Transyss Program
            ts_programs = []
            root = etree.parse(xml_file).getroot()
            ts_programs_node = root.find("TranssysPrograms")
            if ts_programs_node:
                for tp_node in ts_programs_node.iter("TranssysProgram"):
                    ts_program = {}

                    transsys_code = tp_node.find("TranssysCode").text
                    tmp = StringIO.StringIO(transsys_code)
                    parser = TranssysProgramParser(tmp)
                    try:
                        tp = parser.parse_transsys()
                        ts_program["tp"] = tp
                        print tp.name
                    except StandardError, e:
                        print e
                        print transsys_code
                        msg="Unable to compile transsys code"
                        messages.error(request, msg)
                        return render_to_response('importWorkspace.html',
                           context_instance=template.RequestContext(request))
                    ts_programs.append(ts_program)
            
            #Simgenex Program
            sgx_programs = []
            sgx_programs_node = root.find("SimgenexPrograms")
            if sgx_programs_node:
                for sgx_node in sgx_programs_node.iter("SimgenexProgram"):
                    sgx_program = {}
                    sgx_name = sgx_node.get("name")
                    sgx_program["name"] = sgx_name
                    sgx_desc = sgx_node.get("description")
                    sgx_program["desc"] = sgx_desc
                    sgx_code = sgx_node.find("SimgenexCode").text
                    tmp = StringIO.StringIO(sgx_code)
                    sgx_parser = SimGenexObjectiveFunctionParser(tmp)
                    try:
                        sgx = sgx_parser.parse_simgenex()
                        sgx_program["sgx"] = sgx
                    except StandardError, e:
                        msg="Unable to compile transsys code"
                        messages.error(request, msg)
                        messages.error(request, str(e))
                        return render_to_response('importWorkspace.html',
                           context_instance=template.RequestContext(request))
                    #Target transsys program
                    target_tp = []
                    sgx_target_tp_node = sgx_node.find("TargetTranssysPrograms")
                    for target_tp_node in sgx_target_tp_node.iter("TargetTranssysProgram"):
                        target_tp_name = target_tp_node.text
                        tp = _get_transsys_program_by_name(request, target_tp_name)
                        if tp != None:
                            target_tp.append(tp)
                    sgx_program["target_tp"] = target_tp
                    #Target expression data
                    target_expression_data = {}
                    sgx_target_expression_data_node = sgx_node.find("TargetExpressionData")
                    for target_expression_node in sgx_target_expression_data_node.iter("ExpressionSet"):
                        target_expression_name = target_expression_node.get("name")
                        data = StringIO.StringIO(target_expression_node.text)
                        expression_set = ExpressionSet()
                        expression_set.read(data)
                        target_expression_data[target_expression_name] = expression_set
                    sgx_program["target_expression_data"] = target_expression_data
                    sgx_programs.append(sgx_program)
            
            #Initial States
            initial_states = {}
            initial_states_node = root.find("InitialStates")
            if initial_states_node:
                for initial_state_node in initial_states_node.iter("InitialState"):
                    data_set_name = initial_state_node.get("name")
                    initial_states[data_set_name] = {}
                    #fc_list = data_set.find("FactorConcentration")
                    for fc in initial_state_node.iter("FactorConcentration"):
                        f_name = fc.get("name")
                        f_concentration = float(fc.text)
                        initial_states[data_set_name][f_name] = f_concentration
            #Cleaning the session
            request.session.flush()
            request.session["ts_programs"] = ts_programs
            request.session["sgx_programs"] = sgx_programs
            request.session["initial_states"] = initial_states
            request.session.modified = True
            #xml = etree.tostring(root, pretty_print=True, xml_declaration=True)
            return redirect(reverse('tsworkbench.views.ts.home'))
        except ValidationError, e:
            request.session.modified = False
            messages.error(request, e.messages[0])
            return render_to_response('importWorkspace.html',
                                  context_instance=template.RequestContext(request))

#########################################################
def sessionInitilizer(request):
    if not request.session.has_key("ts_programs"):
        request.session["ts_programs"] = []
    if not request.session.has_key("sgx_programs"):
        request.session["sgx_programs"] = []
    if not request.session.has_key("initial_states"):
        request.session["initial_states"] = {}